package practical_projects.games.submarine_war_v2;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;

public class World extends JPanel {             // 世界
    public static final int WIDTH = 641;        // 宽
    public static final int HEIGHT = 479;       // 高
    public static Battleship battleship;        // 战舰
    public static final int seaLevel = 150;     // 海平面
    private int timeCount = 0;
    public static boolean attackFlag = false;   // 战舰是否发射炸弹
    public static boolean startFlag = false;    // 开始游戏标记
    public boolean firstFlag = true;            // 游戏第一次启动标记
    public static boolean pause = false;        // 是否暂停
    public static final int LIFE = 10;          // 战舰初始生命值
    public static final int ATTACK_SPEED = 100; // 水雷潜艇攻击速度，时间单位10ms，每1秒攻击一次
    public static final int PRODUCTION_SPEED = 10; // 生成潜艇的速度，时间单位10ms，每100毫秒（0.1秒）生成一艘潜艇

    private final LinkedList<Submarine> submarineList;  // 潜艇列表
    private final LinkedList<Bomb> bombList;            // 炸弹列表
    private final LinkedList<Mine> mineList;            // 水雷列表

    public World() {
        setSize(WIDTH, HEIGHT);
        battleship = new Battleship();
        submarineList = new LinkedList<>();
        bombList = new LinkedList<>();
        mineList = new LinkedList<>();
    }

    private void start() {
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (!startFlag) {
                    startFlag = true;
                    pause = false;
                    firstFlag = false;
                    submarineList.clear();
                    bombList.clear();
                    mineList.clear();
                    timeCount = 0;
                    battleship.setLife(LIFE);
                    battleship.score = 0;
                    battleship.x = (World.WIDTH - battleship.width) / 2;
                    battleship.setStatus(true);
                }
                else
                    attackFlag = true;
            }
        });
        Timer timer = new Timer();      // 定时器对象
        int interval = 10;      // 定时间隔(单位毫秒)
        timer.schedule(new TimerTask() {
            @Override
            public void run() {     // 定时刷新
                if (startFlag && !pause || firstFlag) {
                    timeCount++;
                    submarineEnter();   // 潜艇入场
                    move();             // 移动
                    attack();           // 攻击
                    check();            // 状态检测
                    settleAccountsAward();  // 结算奖励
                    remove();           // 移除已阵亡或已出界的潜艇、炸弹、水雷
                }
                repaint();  // 重画，超类中的方法，需在最后调用，在move()等方法之前调用可能会抛出异常
            }
        }, interval, interval);
    }

    private void submarineEnter() {
        if (timeCount % PRODUCTION_SPEED == 0)
            submarineList.add(Producer.getSubmarine());
    }

    private void move() {
        battleship.move();
        for (Bomb bomb : bombList) bomb.move();
        for (Mine mine : mineList) mine.move();
        for (Submarine submarine : submarineList) submarine.move();
    }

    private void attack() {     // 攻击
        if (attackFlag) {
            bombList.add(new Bomb(battleship.x, battleship.y));     // 战舰发射炸弹
            attackFlag = false;
        }
        if (timeCount % ATTACK_SPEED == 0)
            for (Submarine submarine : submarineList)
                if (submarine.isLive() && submarine instanceof MineSubmarine) // 水雷潜艇发射水雷
                    mineList.add(new Mine(submarine.x + submarine.width, submarine.y));
    }

    private void check() {      // 状态检测
        for (Bomb bomb : bombList) {
            for (Submarine submarine : submarineList) {
                if (!bomb.isLive())
                    break;
                if (submarine.isLive() && bomb.collisionDetection(submarine)) {
                    submarine.setStatus(false);
                    bomb.setStatus(false);
                }
            }
            if (bomb.isOutBorder())
                bomb.setStatus(false);
        }
        for (Mine mine : mineList) {
            if (startFlag && mine.isLive() && mine.collisionDetection(battleship)) {
                battleship.subtractLife(1);  // 减命
                mine.setStatus(false);
            }
            if (mine.isOutBorder())
                mine.setStatus(false);
        }
        for (Submarine submarine : submarineList)
            if (submarine.isOutBorder())
                submarine.setStatus(false);
        if (battleship.getLife() <= 0) {
            battleship.setStatus(false);
            startFlag = false;
        }
    }

    private void settleAccountsAward() {    // 结算奖励，计分，加
        for (Submarine submarine : submarineList)
            if (!submarine.isLive() && !submarine.isOutBorder()) {
                if (submarine instanceof AwardLife)
                    battleship.addLife(((AwardLife)submarine).getLife());
                else if (submarine instanceof AwardScore)
                    battleship.score += ((AwardScore)submarine).getScore();
            }
    }

    /**
     * 在JDK1.8中，Collection中加入了removeIf方法,其子类自然也继承了此方法
     * default boolean removeIf(Predicate<? super E> filter)    删除满足给定谓词的此集合的所有元素
     * */
    private void remove() {     // 移除阵亡或超界的潜艇、爆炸或超界的炸弹和水雷
        bombList.removeIf(bomb -> !bomb.isLive());
        mineList.removeIf(mine -> !mine.isLive());
        submarineList.removeIf(submarine -> !submarine.isLive());
    }


    /**
     * 绘画
     * Graphics     画笔
     * */
    @Override
    public synchronized void paint(Graphics g) {
        Images.sea.paintIcon(null, g, 0, 0);
        g.drawString("life：" + battleship.getLife(), 50, 30);
        g.drawString("score：" + battleship.score, 511, 30);
        battleship.paintImage(g);
        for (Submarine submarine : submarineList)
            submarine.paintImage(g);
        for (Bomb bomb : bombList)
            bomb.paintImage(g);
        for (Mine mine : mineList)
            mine.paintImage(g);
        if (!startFlag && battleship.isLive()) {
            g.drawString("开始游戏", (WIDTH - 50) / 2, (HEIGHT - 30) / 2);
        }
        if (!battleship.isLive())
            Images.gameOver.paintIcon(null, g, 0, 0);
    }

    public static void main(String[] args){
        JFrame jFrame = new JFrame("潜艇大战");
        jFrame.setSize(WIDTH + 16, HEIGHT + 39);
        jFrame.setLocationRelativeTo(null); // 设置窗口相对于指定组件的位置
                                            // 如果组件当前未显示或者参数 c 为 null，则此窗口将置于屏幕的中央
        jFrame.setLayout(null);
        World world = new World();
        jFrame.add(world);
        jFrame.setVisible(true);
        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {      // 键入键时调用

            }

            @Override
            public void keyPressed(KeyEvent e) {    // 按下键时调用
                if (World.startFlag) {
                    char key=e.getKeyChar();
                    int k = e.getKeyCode();
                    if (e.isControlDown())  // 判断是否按下Ctrl键，按下Ctrl键暂停游戏
                        pause = !pause;
                    if (key == 'a' || k == KeyEvent.VK_LEFT)
                        World.battleship.setDirection(-1);
                    else if (k == KeyEvent.VK_D || k == KeyEvent.VK_RIGHT)
                        World.battleship.setDirection(1);
                    if (k == KeyEvent.VK_SPACE)     // 判断是否按下空格键，按下空格键则战舰发射炸弹
                        attackFlag = true;
                }
            }

            @Override
            public void keyReleased(KeyEvent e) {   // 当键已被释放时调用

            }
        });
        world.start();
    }
}
